package com.ys.erp.stage_user_service.service;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ys.erp.common.util.YsThread;
import com.ys.erp.entity.data.bean.*;
import com.ys.erp.entity.service.*;
import com.ys.erp.framework.bean.dto.StageEmpDTO;
import com.ys.erp.framework.exception.YsException;
import com.ys.erp.framework.response.PageDTO;
import com.ys.erp.stage_user_service.bean.condition.UserComplaintCondition;
import com.ys.erp.stage_user_service.bean.event.UserComplaintEvent;
import com.ys.erp.stage_user_service.bean.vo.ComplaintVO;
import com.ys.erp.stage_user_service.bean.vo.StrongComplaintVO;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 南山
 * @date 2025/07/08 14:25
 */
@Service
@RequiredArgsConstructor
public class UserComplaintService {

    private final IUserCatService iUserCatService;
    private final ICatService iCatService;
    private final IComplaintService iComplaintService;

    private final IStrongComplaintService iStrongComplaintService;

    private final IStrongComplaintRecordService iStrongComplaintRecordService;

    private final ApplicationEventPublisher eventPublisher;

    public PageDTO<ComplaintVO> pageComplaint(StageEmpDTO empDto, UserComplaintCondition.@Valid PageComplaintCon con) {
        Page<Complaint> complaintPage = new Page<>(con.getCurrent(), con.getSize());
        QueryWrapper<Complaint> complaintQw = getComplaintQw(con);
        Page<Complaint> page = iComplaintService.page(complaintPage, complaintQw);
        if (page.getRecords().isEmpty()) {
            return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        List<Complaint> complaintList = page.getRecords();

        CompletableFuture<Map<String, UserCat>> userCatMapFuture = YsThread.execute(() -> {
            List<Long> userIdList = complaintList.stream().map(Complaint::getUserId).toList();
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().in(UserCat::getUserId, userIdList);
            List<UserCat> userCatList = iUserCatService.list(userCatQw);
            return userCatList.stream()
                    .collect(Collectors.toMap(it -> it.getUserId() + "-" + it.getCatCode(), Function.identity()));
        });
        Map<String, UserCat> userCatMap = userCatMapFuture.join();
        ArrayList<ComplaintVO> resultList = new ArrayList<>();
        for (Complaint complaint : complaintList) {
            ComplaintVO vo = new ComplaintVO();
            BeanUtils.copyProperties(complaint, vo);
            vo.setAnnexFile(JSONArray.parseArray(complaint.getAnnexFile(), String.class));
            vo.setDiseaseType(JSONArray.parseArray(complaint.getDiseaseType(), String.class));
            vo.setComplaintDate(complaint.getComplaintDate());
            UserCat userCat = userCatMap.get(complaint.getUserId() + "-" + complaint.getCatCode());
            if (Objects.isNull(userCat)) {
                userCat = userCatMap.get(complaint.getUserId() + "-" + complaint.getCatCode().toLowerCase());
                if (Objects.isNull(userCat)) {
                    resultList.add(vo);
                    continue;
                }
            }
            vo.setAdoptDay(userCat.getAdoptDay());
            vo.setTakeDate(userCat.getTakeDate());
            resultList.add(vo);
        }
        return new PageDTO<>(1L, page.getTotal(), resultList);
    }


    public QueryWrapper<Complaint> getComplaintQw(UserComplaintCondition.@Valid PageComplaintCon con) {
        QueryWrapper<Complaint> complaintQw = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(con.getCatCode())) {
            complaintQw.lambda().like(Complaint::getCatCode, con.getCatCode());
        }
        if (ObjectUtil.isNotEmpty(con.getShopCode())) {
            complaintQw.lambda().like(Complaint::getShopCode, con.getShopCode());
        }
        if (ObjectUtil.isNotEmpty(con.getSeekType())) {
            complaintQw.lambda().eq(Complaint::getSeekType, con.getSeekType());
        }
        if (ObjectUtil.isNotEmpty(con.getDiseaseType())) {
            complaintQw.lambda().eq(Complaint::getDiseaseType, con.getDiseaseType());
        }
        if (ObjectUtil.isNotEmpty(con.getProblemType())) {
            complaintQw.lambda().eq(Complaint::getProblemType, con.getProblemType());
        }
        if (ObjectUtil.isNotEmpty(con.getDisposeStatus())) {
            complaintQw.lambda().eq(Complaint::getDisposeStatus, con.getDisposeStatus());
        }
        if (ObjectUtil.isNotEmpty(con.getAdoptType())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().select(UserCat::getUserId);
            userCatQw.lambda().eq(UserCat::getContractType, con.getAdoptType());
            List<Long> userIdList = iUserCatService.list(userCatQw)
                    .stream().map(UserCat::getUserId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(userIdList)) {
                complaintQw.lambda().in(Complaint::getUserId, -1);
            } else {
                complaintQw.lambda().in(Complaint::getUserId, userIdList);
            }

        }

        if (ObjectUtil.isNotEmpty(con.getPetType())) {
            QueryWrapper<Cat> catQw = new QueryWrapper<>();
            catQw.lambda().select(Cat::getCatCode);
            catQw.lambda().eq(Cat::getPetType, con.getAdoptType());
            List<String> catCodeList = iCatService.list(catQw)
                    .stream().map(Cat::getCatCode).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(catCodeList)) {
                complaintQw.lambda().in(Complaint::getCatCode, -1);
            } else {
                complaintQw.lambda().in(Complaint::getCatCode, catCodeList);
            }

        }
        if (ObjectUtil.isNotEmpty(con.getAdoptNum())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().select(UserCat::getUserId);
            List<UserCat> userCatList = iUserCatService.list(userCatQw);
            Map<Long, Long> userCountMap = userCatList.stream()
                    .collect(Collectors.groupingBy(UserCat::getUserId, Collectors.counting()));
            List<Long> userIdList;
            if (con.getAdoptNum() == 1) {
                userIdList = userCountMap.entrySet().stream()
                        .filter(entry -> entry.getValue() == 1)
                        .map(Map.Entry::getKey).collect(Collectors.toList());
            } else {
                userIdList = userCountMap.entrySet().stream()
                        .filter(entry -> entry.getValue() > 1)
                        .map(Map.Entry::getKey).collect(Collectors.toList());
            }
            if (CollectionUtils.isEmpty(userIdList)) {
                complaintQw.lambda().in(Complaint::getUserId, -1);
            } else {
                complaintQw.lambda().in(Complaint::getUserId, userIdList);
            }
        }
        if (StringUtils.isNotBlank(con.getStartDate()) && StringUtils.isNotBlank(con.getEndDate())) {
            complaintQw.lambda().ge(Complaint::getComplaintDate, con.getStartDate() + " 00:00:00");
            complaintQw.lambda().le(Complaint::getComplaintDate, con.getEndDate() + " 23:59:59");
        }
        if ("desc".equals(con.getDescOrAsc())) {
            complaintQw.lambda().orderByDesc(Complaint::getComplaintDate);
        } else {
            complaintQw.lambda().orderByAsc(Complaint::getComplaintDate);
        }
        return complaintQw;
    }

    /**
     * 分页用户投诉
     *
     * @param empDto                    登录员工
     * @param con                       分页请求体
     * @return                          投诉列表
     */
    public PageDTO<StrongComplaintVO> pageStrongComplaint(StageEmpDTO empDto, UserComplaintCondition.PageStrongComplaintCon con) {
        Page<StrongComplaint> strongComplaintPage = new Page<>(con.getCurrent(), con.getSize());
        //构造条件
        QueryWrapper<StrongComplaint> comQw = new QueryWrapper<>();
        if (ObjectUtils.isNotEmpty(con.getUserId())) {
            comQw.lambda().eq(StrongComplaint::getUserId, con.getUserId());
        }
        if (ObjectUtil.isNotEmpty(con.getRelaNo())) {
            comQw.lambda().eq(StrongComplaint::getRelaNo, con.getRelaNo());
        }
        //查询类型，0待接入，1我的处理中，2处理完成带用户确认，3已结束
        switch (con.getQueryType()) {
            case 0:
                comQw.lambda().eq(StrongComplaint::getComplaintStatus, StrongComplaint.Enums.UN_DIS.name());
                comQw.lambda().orderByDesc(StrongComplaint::getInitTime);
                break;
            case 1:
                comQw.lambda().eq(StrongComplaint::getComplaintStatus, StrongComplaint.Enums.DIS_START.name());
                comQw.lambda().eq(StrongComplaint::getDisEmpId, empDto.getId());
                comQw.lambda().orderByDesc(StrongComplaint::getStartTime);
                break;
            case 2:
                comQw.lambda().eq(StrongComplaint::getComplaintStatus, StrongComplaint.Enums.DIS_OK.name());
                comQw.lambda().orderByDesc(StrongComplaint::getOkTime);
                break;
            case 3:
                comQw.lambda().in(StrongComplaint::getComplaintStatus, StrongComplaint.Enums.DIS_SOLVE.name(), StrongComplaint.Enums.DIS_UN_SOLVE.name());
                comQw.lambda().orderByDesc(StrongComplaint::getOkTime);
                break;
        }
        Page<StrongComplaint> page = iStrongComplaintService.page(strongComplaintPage, comQw);
        if (page.getRecords().isEmpty()) {
            return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        List<String> noList = page.getRecords().stream().map(StrongComplaint::getComplaintNo).toList();
        Map<String, List<StrongComplaintRecord>> recordMap = iStrongComplaintRecordService.mapByNoList(noList);
        List<StrongComplaintVO> resultList = page.getRecords().stream().map(complaint -> {
            StrongComplaintVO vo = new StrongComplaintVO();
            vo.setComplaintNo(complaint.getComplaintNo());
            vo.setRelaNo(complaint.getRelaNo());
            vo.setComplaintContent(complaint.getComplaintContent());
            vo.setComplaintImage(complaint.getComplaintImageList());
            vo.setComplaintType(complaint.getComplaintType());
            vo.setPhone(complaint.getPhone());
            vo.setComplaintStatus(complaint.getComplaintStatus());
            vo.setInitTime(complaint.getInitTime());
            vo.setEmpName(complaint.getDisEmpName());
            vo.setDisDes(complaint.getComplaintPlan());
            List<StrongComplaintRecord> recordList = recordMap.get(complaint.getComplaintNo());
            List<StrongComplaintVO.RecordVO> recordVoList = recordList.stream().map(record -> {
                StrongComplaintVO.RecordVO recordVO = new StrongComplaintVO.RecordVO();
                recordVO.setRecordTime(record.getRecordTime());
                recordVO.setRecordType(record.getRecordType());
                recordVO.setDisDescribe(record.getDisDescribe());
                recordVO.setDisImage(record.getComplaintImageList());
                return recordVO;
            }).toList();
            vo.setRecordList(recordVoList);
            return vo;
        }).toList();
        return new PageDTO<>(page.getCurrent(), page.getTotal(), resultList);
    }

    /**
     * 接入处理投诉
     *
     * @param empDto                    登录员工
     * @param complaintNo               投诉单号
     */
    public void disComplaint(StageEmpDTO empDto, String complaintNo) {
        StrongComplaint complaint = iStrongComplaintService.getByNo(complaintNo);
        if (ObjectUtils.isEmpty( complaint)) {
            throw new YsException(-1, "此条客诉不存在");
        }
        if (!StrongComplaint.Enums.UN_DIS.name().equals(complaint.getComplaintStatus())) {
            throw new YsException(-1, "此投诉单状态无法处理");
        }
        complaint.setStartTime(LocalDateTime.now());
        complaint.setComplaintStatus(StrongComplaint.Enums.DIS_START.name());
        complaint.setDisEmpId(empDto.getId());
        complaint.setDisEmpName(empDto.getRealName());
        iStrongComplaintService.updateById(complaint);
        eventPublisher.publishEvent(new UserComplaintEvent(complaint, new ArrayList<>()));
    }

    /**
     * 处理完成
     *
     * @param empDto                登录员工
     * @param con                   请求体
     */
    public void disComplaintOk(StageEmpDTO empDto, UserComplaintCondition.DisComplaintOkCon con) {
        StrongComplaint complaint = iStrongComplaintService.getByNo(con.getComplaintNo());
        if (ObjectUtils.isEmpty( complaint)) {
            throw new YsException(-1, "此条客诉不存在");
        }
        if (!StrongComplaint.Enums.DIS_START.name().equals(complaint.getComplaintStatus())) {
            throw new YsException(-1, "此投诉单状态无法处理");
        }
        complaint.setComplaintStatus(StrongComplaint.Enums.DIS_OK.name());
        complaint.setOkTime(LocalDateTime.now());
        complaint.setComplaintPlan(con.getDisDescribe());
        iStrongComplaintService.updateById(complaint);
        eventPublisher.publishEvent(new UserComplaintEvent(complaint, con.getDisImageList()));
    }

}
